package com.alpha.gateway.service;

import com.alpha.core.exception.AlphaException;
import com.alpha.core.http.AlphaHttpContext;
import com.alpha.core.http.HttpConstants;
import com.alpha.core.utils.DateUtil;
import com.alpha.feign.common.entity.Tenant;
import com.alpha.feign.common.entity.User;
import com.alpha.gateway.schemas.users_logs.UserLog;
import com.alpha.gateway.schemas.users_logs.UserLogService;
import com.alpha.gateway.utils.TokenUtil;
import com.alpha.gateway.utils.RequestUtil;
import com.google.common.collect.ImmutableMap;
import lombok.RequiredArgsConstructor;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Map;
import java.util.TreeMap;

/**
 * 用户认证(验证某个用户是否为系统中的合法主体，能否访问该系统，即验证用户名和密码)
 *
 * @author chenruwan
 * @since 2022-01-01
 */
@Service
@RequiredArgsConstructor
public class AuthenticationService {
    private final UserLogService userLogService;

    private final FeignClientService feignClientService;

    public void checkTenant(User user) {
        if (user.getTenantId() == null) {
            return;
        }

        Tenant tenant = feignClientService.getTenant(user.getTenantId());
        if (tenant == null) {
            throw new AlphaException("用户所在企业不存在");
        }
        if (Boolean.FALSE.equals(tenant.getEnabled())) {
            throw new AlphaException("用户所在企业已被关闭");
        }
        if (tenant.getExpirationDate().before(DateUtil.today())) {
            throw new AlphaException("用户所在企业已过期");
        }
    }

    public Map<String, String> makeToken(User user) {
        Map<String, String> claims = new TreeMap<>();
        claims.put(HttpConstants.CLAIM_USER_ID, user.getId().toString());
        claims.put(HttpConstants.CLAIM_USER_NAME, user.getUsername());
        if (user.getTenantId() != null) {
            claims.put(HttpConstants.CLAIM_TENANT_ID, user.getTenantId().toString());
        }

        return ImmutableMap.<String, String>builder()
                .putAll(claims)
                .put("access_token", TokenUtil.createToken(claims))
                .put("token_type", "bearer")
                .build();
    }

    public void saveUserLog(User user, Long tenantId, boolean successful, ServerHttpRequest request) {
        UserLog userLog = new UserLog().setUserId(user.getId())
                .setTenantId(tenantId)
                .setClient(AlphaHttpContext.getClientName())
                .setSuccessful(successful)
                .setLoginIp(RequestUtil.getRemoteIp(request))
                .setLoginTime(new Date())
                .setCreatedBy(user.getUsername())
                .setUpdatedBy(user.getUsername())
                .build();
        userLogService.save(userLog);
    }
}
